package v1

import (
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/satori/go.uuid"
	"go.uber.org/zap"
	"guns-go/global"
	"guns-go/middleware"
	"guns-go/model"
	"guns-go/model/request"
	"guns-go/model/response"
	"guns-go/service"
	"guns-go/utils"
	"strconv"
	"time"
)

// @Tags SysUser
// @Summary 用户登录
// @Produce  application/json
// @Param data body request.Login true "账号, 密码"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /login [post]
func Login(c *gin.Context) {
	var L request.Login
	_ = c.ShouldBindJSON(&L)

	//判断请求数据是否为空
	if err := utils.Verify(L, utils.LoginVerify); err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}

	U := &model.SysUser{Account: L.Account, Password: L.Password}
	//查询用户
	if err, user := service.Login(U); err != nil {
		global.GVA_LOG.Error("登陆失败! 用户名不存在或者密码错误", zap.Any("err", err))
		response.FailWithMessage("用户名不存在或者密码错误", c)
	} else if U.Status == 1 {
		global.GVA_LOG.Error("登陆失败! 账号被冻结，请联系管理员", zap.Any("err", err))
		response.FailWithMessage("账号被冻结，请联系管理员", c)
	} else {
		//生成token
		tokenNext(c, *user)
	}
}

// 登录以后签发jwt
func tokenNext(c *gin.Context, user model.SysUser) {
	// 唯一签名
	j := &middleware.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)}

	//查询用户角色
	err, userRoleIds := service.GetUserRoleIdList(user.Id)

	if err != nil {
		global.GVA_LOG.Error("获取token失败", zap.Any("err", err))
		response.FailWithMessage("获取token失败", c)
		return
	}

	claims := request.CustomClaims{
		ID:          user.Id,
		NickName:    user.NickName,
		Username:    user.Name,
		Account:     user.Account,
		UserRoleIds: userRoleIds,
		AdminType:   user.AdminType,
		Uuid:        uuid.NewV4(),
		// 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
		BufferTime: global.GVA_CONFIG.JWT.BufferTime,
		StandardClaims: jwt.StandardClaims{
			// 签名生效时间
			NotBefore: time.Now().Unix() - 1000,
			// 过期时间 7天  配置文件
			ExpiresAt: time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime,
			// 签名的发行者
			Issuer: "qmPlus",
		},
	}
	//生成token
	token, err := j.CreateToken(claims)
	if err != nil {
		global.GVA_LOG.Error("获取token失败", zap.Any("err", err))
		response.FailWithMessage("获取token失败", c)
		return
	}

	//缓存用户信息 uuid作为key
	if err := service.SetRedisJWT(claims.Uuid, user); err != nil {
		global.GVA_LOG.Error("设置登录状态失败", zap.Any("err", err))
		response.FailWithMessage("设置登录状态失败", c)
		return
	}

	//更新最后登陆ip和时间
	if err = service.UpdateByUserId(c.ClientIP(), user.Id); err != nil {
		response.FailWithMessage("更新数据库异常", c)
		return
	}

	//TODO 登陆成功，异步记录登陆日志

	response.OkWithData(token, c)
}

// @Tags SysUser
// @Summary 获取登陆用户信息
// @Security ApiKeyAuth
// @Produce  application/json
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /getLoginUser [get]
func GetLoginUser(c *gin.Context) {

	userId := GetUserID(c)
	err, info := service.GenSysLoginUser(userId, c)

	if err != nil {
		response.FailWithMessage("获取登陆用户信息异常", c)
		return
	}

	response.OkWithData(info, c)
}

// @Tags SysUser
// @Summary 用户退出登陆
// @Security ApiKeyAuth
// @Produce  application/json
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /logout [get]
func Logout(c *gin.Context) {

	gUuid := service.GetUuid(c)
	err := service.DelRedisJWT(gUuid)

	if err != nil {
		response.Fail(c)
	}
	response.OkWithDetailed("退出登陆", "退出成功", c)
}

// 从Gin的Context中获取从jwt解析出来的用户ID
func GetUserID(c *gin.Context) int {
	if claims, exists := c.Get("claims"); !exists {
		global.GVA_LOG.Error("从Gin的Context中获取从jwt解析出来的用户ID失败, 请检查路由是否使用jwt中间件")
		return 0
	} else {
		waitUse := claims.(*request.CustomClaims)
		return waitUse.ID
	}
}

// @Tags SysUser
// @Summary 用户分页查询
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/page [get]
func UserPage(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindQuery(&U)

	err, UserPageResult := service.UserPage(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(UserPageResult, c)
}

// @Tags SysUser
// @Summary 用户详情查询
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/detail [get]
func UserDetail(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindQuery(&U)

	err, UserResult := service.UserDetail(U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(UserResult, c)
}

// @Tags SysUser
// @Summary 用户重置密码
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/resetPwd [post]
func ResetPwd(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.ResetPwd(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 用户角色
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/ownRole [get]
func OwnRole(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindQuery(&U)

	err, roleIds := service.OwnRole(&U)

	ids := make([]string, 0)

	if len(roleIds) > 0 {
		for _, id := range roleIds {
			ids = append(ids, strconv.Itoa(id))
		}
	}
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(ids, c)
}

// @Tags SysUser
// @Summary 用户数据权限
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/ownData [get]
func OwnData(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindQuery(&U)

	err, scopeIds := service.OwnData(&U)

	ids := make([]string, 0)

	if len(scopeIds) > 0 {
		for _, id := range scopeIds {
			ids = append(ids, strconv.Itoa(id))
		}
	}
	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(ids, c)
}

// @Tags SysUser
// @Summary 删除用户
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/delete [post]
func UserDelete(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UserDelete(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 新增用户
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/add [post]
func UserAdd(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UserAdd(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 修改用户
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/edit [post]
func UserEdit(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UserEdit(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 用户授权角色
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/grantRole [post]
func UserGrantRole(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UserGrantRole(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 用户授权数据权限
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/grantData [post]
func UserGrantData(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UserGrantData(&U, c)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 用户修改状态
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/changeStatus [post]
func ChangeStatus(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.ChangeStatus(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 更新用户信息
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/updateInfo [post]
func UpdateUserInfo(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UpdateUserInfo(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 更新用户密码
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/updatePwd [post]
func UpdatePwd(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UpdatePwd(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 更新用户头像
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/updateAvatar [post]
func UpdateAvatar(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindJSON(&U)

	err := service.UpdateAvatar(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.Ok(c)
}

// @Tags SysUser
// @Summary 获取用户下拉框数据
// @Security ApiKeyAuth
// @accept application/json
// @Produce  application/json
// @Param data body request.SysUserParam true "请求参数"
// @Success 200 {string} string "{"success":true,"data":{},"message":"请求成功","code":200}"
// @Router /sysUser/selector [get]
func Selector(c *gin.Context) {

	var U request.SysUserParam
	_ = c.ShouldBindQuery(&U)

	err, UserResult := service.Selector(&U)

	if err != nil {
		response.FailWithMessage(err.Error(), c)
		return
	}
	response.OkWithData(UserResult, c)
}
